﻿using SuperX.Common.Abstract;
using SuperX.Common;
using SuperX.DataService.Abstract;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Timers;
using SuperX.DataService.Helper;
using HslCommunication.Core;
using SuperX.Common.Log;
using NPOI.SS.Formula.Functions;

namespace SuperX.DataService
{
    public sealed class ModbusGroup : PLCGroup
    {
        public ModbusGroup(string name, int updateRate, bool active, IPLCDriver plcReader, IByteTransform byteTransform) : base(name, updateRate, active, plcReader)
        {
            ByteTransform = byteTransform;
        }

        public IByteTransform ByteTransform { get; }

        protected override unsafe void Poll()
        {
            DateTime dt = DateTime.Now;
            bool[] rcvBools = null;
            byte[] rcvBytes = null;
            try
            {
                foreach (PDUArea area in _rangeList)
                {
                    var DigitalTag = area.Start.GatherType;
                    if (DigitalTag == GatherType.Digital)
                        rcvBools = _plcReader.ReadBools(area.Start, (ushort)(area.Len));
                    else
                        rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据
                    if ((DigitalTag != GatherType.Digital && (rcvBytes == null || rcvBytes.Length == 0)) || DigitalTag == GatherType.Digital && (rcvBools == null || rcvBools.Length == 0))
                    {
                        continue;
                    }
                    else
                    {
                        int index = area.StartIndex;//index指向_items中的Tag元数据
                        int count = index + area.Count;
                        while (index < count)
                        {
                            var tag = _items[index];
                            DeviceAddress addr = tag.Address;
                            var offset = DigitalTag == GatherType.Digital ? addr.Start - area.Start.Start : (addr.Start - area.Start.Start) * 2;
                            var bitOffset = DigitalTag == GatherType.Digital ? addr.Start - area.Start.Start : (addr.Start - area.Start.Start) * 16 + addr.Bit;
                            ByteTransformConverter.UpdateTagValue(tag, ByteTransform, tag.Address.VarType, rcvBytes, offset, tag.Address.DataSize, rcvBools, bitOffset, TransBool);
                            index++;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Warn($"分组名:{this.FullName}，采集错误，信息：{e.Message}");
            }
        }

        protected override int ConvertLength(int length, DeviceAddress end)
        {
            if (end.GatherType == GatherType.Digital)
                return length;
            else
            {
                switch (end.VarType)
                {
                    case DataType.BYTE:
                        return length + 1;

                    case DataType.SHORT:
                    case DataType.WORD:
                        return length + 1;

                    case DataType.DWORD:
                    case DataType.INT:
                    case DataType.FLOAT:
                        return length + 4;

                    default:
                        return length;
                }
            }
        }

        private bool TransBool(bool[] boolsRcv, byte[] rcvBytes, int offset, out bool res)
        {
            res = true;
            if (boolsRcv == null || boolsRcv.Length < offset)
            {
                res = false;
                return false;
            }
            return boolsRcv[offset];
        }
    }
}